package com.david.viewtest.view

import android.content.Context
import android.graphics.Bitmap
import android.graphics.BitmapFactory
import android.graphics.Canvas
import android.graphics.Paint
import android.graphics.Rect
import android.util.AttributeSet
import android.util.Log
import android.view.MotionEvent
import android.view.VelocityTracker
import android.view.View
import android.view.ViewConfiguration
import android.widget.Scroller
import com.david.viewtest.R
import kotlin.math.abs

class BigImgView(
    context: Context,
    attrs: AttributeSet,
) : View(context, attrs) {
    private val imgRect = Rect()
    private val dstRect = Rect()

    private val bitmap: Bitmap = BitmapFactory.decodeResource(context.resources, R.mipmap.example, null)

    var paint = Paint()

    var imgWidthHeightRatio = bitmap.width.toFloat()/bitmap.height
    private var viewWidthHeightRatio = bitmap.width.toFloat()/bitmap.height

    init {
        imgRect.right = bitmap.width
        imgRect.bottom = bitmap.height

        Log.e("imgWidthHeightRatio", "imgWidthHeightRatio: $imgWidthHeightRatio")
    }

    override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec)
        dstRect.right = measuredWidth
        dstRect.bottom = measuredHeight

        width = measuredWidth
        height = measuredHeight

        viewWidthHeightRatio = measuredWidth / measuredHeight.toFloat()

        setRect()
    }

    override fun onDraw(canvas: Canvas) {
        //super.onDraw(canvas)
        canvas.drawBitmap(bitmap, imgRect, dstRect, paint)
    }


    // 上一次触摸事件的y坐标
    private var lastX = 0f
    private var lastY = 0f

    private var lastX2 = 0f
    private var lastY2 = 0f


    // 用来算速度的工具（通过在每次的触摸事件中打点）
    private var mVelocityTracker: VelocityTracker = VelocityTracker.obtain()

    // 用来根据传入的速度算当前应该滚动到的位置的工具
    private val scroller by lazy { Scroller(context) }

    private var isActionUp = false
    private var eventCopy: MotionEvent? = null
    private var eventX = 0f
    private var eventY = 0f
    private var dx = 0f
    private var dy = 0f
    private var maxV = 0f
    private var xVelocity = 0f
    private var yVelocity = 0f

    private var isScale = false

    override fun onTouchEvent(event: MotionEvent): Boolean {
        if (!scroller.isFinished) {
            scroller.abortAnimation();
        }
        if (!super.onTouchEvent(event)) {
            isActionUp = false
            // 拷贝一份触摸事件，我猜是为了防止污染原事件
            eventCopy = MotionEvent.obtain(event)

            eventX = event.x
            eventY = event.y

            when(event.actionMasked) {
                MotionEvent.ACTION_DOWN -> {
                    lastX = eventX
                    lastY = eventY

                    if (event.pointerCount == 2) {
                        lastX2 = event.getX(1)
                        lastY2 = event.getY(1)
                    }
                }
                MotionEvent.ACTION_MOVE -> {
                    if (event.pointerCount == 2) {
                        scale = abs(event.getY(0) - event.getY(1)) / abs(lastY - lastY2)

                        Log.e("scale", "scale is :$scale")
                        setRect()

                        isScale = true
                        postInvalidate()
                        return true
                    }


                    dx = lastX - eventX
                    dy = lastY - eventY
                    scrollTo((scrollX + dx).toInt(), (scrollY + dy).toInt())
                    lastX = eventX
                    lastY = eventY
                }
                MotionEvent.ACTION_UP -> {
                    if (isScale) {
                        return true
                    }

                    // 最后一次打点
                    mVelocityTracker.addMovement(eventCopy)
                    isActionUp = true
                    // 设定一个最大速度，速度太快体验也不好
                    maxV = ViewConfiguration.get(context).scaledMaximumFlingVelocity.toFloat()
                    // 这里的 1000 是你想要的速度单位。值1提供像素/毫秒，1000提供像素/秒
                    mVelocityTracker.computeCurrentVelocity(1000, maxV)
                    xVelocity = -mVelocityTracker.getXVelocity(event.getPointerId(0))
                    yVelocity = -mVelocityTracker.getYVelocity(event.getPointerId(0))

                    startFling(xVelocity.toInt(), yVelocity.toInt())

                    mVelocityTracker.clear()
                }
                else -> {}
            }

            if (!isActionUp) {
                // 每次触摸事件打点
                mVelocityTracker.addMovement(eventCopy)
            }
            eventCopy?.recycle()

            return true
        }

        return false
    }


    private var scale = 1f
    private var dstWidth = 0//目标宽度
    private var dstHeight = 0//目标高度
    private var width = 0//控件宽度
    private var height = 0//控件高度
    private fun setRect() {
        if(imgWidthHeightRatio > viewWidthHeightRatio) {//img与view同宽度时img的高度小，使用view宽度
            dstWidth = (width * scale).toInt()
            dstRect.left = (width - dstWidth)/2
            dstRect.right = dstRect.left + dstWidth

            dstHeight = (dstWidth / imgWidthHeightRatio).toInt()
            dstRect.top = (height - dstHeight) / 2
            dstRect.bottom = dstRect.top + dstHeight
        } else {//img与view同高度时view的高度更小
            dstHeight = (height * scale).toInt()
            dstRect.top = (height - dstHeight)/2
            dstRect.bottom = dstRect.top + dstHeight

            dstWidth = (dstHeight * imgWidthHeightRatio).toInt()
            dstRect.left = (width - dstWidth) / 2
            dstRect.right = dstRect.left + dstWidth
        }
    }

    private val refreshRunnable = Runnable {
        if (scroller.computeScrollOffset()) {
            scrollTo(scroller.currX, scroller.currY)
            postOnAnimationFun()
        }
    }

    private fun postOnAnimationFun() {
        // 使Runnable在下一个动画时间步长上执行
        postOnAnimation (refreshRunnable)
    }

    private fun startFling(velocityX: Int, velocityY: Int) {
        // 通知scroller开始计算应该活动到的位置
        scroller.fling(scrollX, scrollY, velocityX, velocityY, Int.MIN_VALUE, Int.MAX_VALUE, Int.MIN_VALUE, Int.MAX_VALUE)

        postOnAnimationFun()
    }

    private var realHeight = 0
    private var newY = 0
    override fun scrollTo(x: Int, y: Int) {
        realHeight = height
        newY = if (y < 0) 0
        else if (y > realHeight) realHeight
        else y
        super.scrollTo(x, newY)
    }

    //private var tempHeight = 0
    //private fun getRealHeight(): Int {
    //    tempHeight = 0
    //    for(index in 0 until childCount) {
    //        tempHeight += getChildAt(index).height
    //    }
    //    return tempHeight - this.height
    //}
}